package biz

import (
	"New-lesson-part2/custom_error"
	"New-lesson-part2/internal"
	"New-lesson-part2/model"
	"New-lesson-part2/proto/pb"
	"context"
	"errors"
	"fmt"
	"github.com/golang/protobuf/ptypes/empty"
)

type ProductServer struct { //biz目录里面创建使用的是ProductserviceServer ctrl+i 创建的product空结构体即可
}

//Product商品相关操作

func (p ProductServer) CreateProduct(ctx context.Context, req *pb.CreateProductItem) (*pb.ProductItemRes, error) {
	var category model.CateGory
	var brand model.Brand
	//var res *pb.ProductItemRes
	r := internal.DB.First(&category, req.CategoryId)
	if r.RowsAffected < 1 {
		return nil, errors.New(custom_error.BrandDoesNotExist)
	}
	r = internal.DB.First(&brand, req.BrandId)
	if r.RowsAffected < 1 {
		return nil, errors.New(custom_error.CategoryDoesNotExist)
	}
	req2Model := ConvertReq2Model(req, category, brand)
	r = internal.DB.Save(&req2Model)
	if r.RowsAffected < 1 {
		return nil, errors.New(custom_error.ProductCreateDataFailed)
	}
	res := CovertProductModel2pb(req2Model)
	return res, nil
}

func (p ProductServer) DeleteProduct(ctx context.Context, req *pb.ProductDelItem) (*empty.Empty, error) {
	var pro model.Product
	tx := internal.DB.Delete(&pro, req.Id)
	if tx.Error != nil {
		return nil, errors.New(custom_error.ProductDeleteSystemError)
	}
	if tx.RowsAffected < 1 {
		return nil, errors.New(custom_error.ProductDeleteFailed)
	}
	return &empty.Empty{}, nil
}

func (p ProductServer) UpdateProduct(ctx context.Context, req *pb.CreateProductItem) (*empty.Empty, error) {
	var pro model.Product
	var cb model.ProductCategoryBrand
	var cate model.CateGory
	var brand model.Brand
	cate.ID = cb.CategoryID
	brand.ID = cb.BrandID
	r := internal.DB.Where(&model.ProductCategoryBrand{CategoryID: cate.ID}).Where(&model.ProductCategoryBrand{BrandID: brand.ID}).First(&cb)
	r = internal.DB.First(&pro, req.Id)
	if r.RowsAffected < 1 {
		return nil, errors.New(custom_error.ProductDataIsNotExists)
	}
	req2Model := ConvertReq2Model(req, cate, brand)
	save := internal.DB.Updates(&req2Model)
	if save.RowsAffected < 1 {
		return nil, errors.New(custom_error.UpdateProductFailed)
	}
	return &empty.Empty{}, nil
}

func (p ProductServer) ProductList(ctx context.Context, req *pb.ProductConditionReq) (*pb.ProductsRes, error) {
	iDb := internal.DB.Model(model.Product{})
	var productList []model.Product
	var itemList []*pb.ProductItemRes
	var res pb.ProductsRes
	if req.IsPop {
		iDb = iDb.Where("is_pop = ?", req.IsPop)
	}
	if req.IsNew {
		iDb = iDb.Where("is_new = ?", req.IsNew)
	}
	if req.BrandId > 0 {
		iDb = iDb.Where("brand_id = ?", req.BrandId)
	}
	if req.KeyWord != "" {
		iDb = iDb.Where("Key_word like ?", "%"+req.KeyWord+"%")
	}
	if req.MaxPrice > 0 {
		iDb = iDb.Where("Max_price = ?", req.MaxPrice)
	}
	if req.MinPrice >= 0 {
		iDb = iDb.Where("min_price = ?", req.MinPrice)
	}
	if req.CategoryId > 0 {
		var cate model.CateGory
		r := internal.DB.First(&cate, req.CategoryId)
		if r.RowsAffected < 1 {
			return nil, errors.New(custom_error.ProductDataIsNotExists)
		}
		var q string
		if cate.Level == 1 {
			q = fmt.Sprintf("select id from category where parent_category_id in(select id from category where parent_category_id = %d )", req.CategoryId)
		} else if cate.Level == 2 {
			q = fmt.Sprintf("select id from category where parent_category_id = %d", req.CategoryId)
		} else if cate.Level == 3 {
			q = fmt.Sprintf("select id from category where id = %d", req.CategoryId)
		}
		iDb = iDb.Where(fmt.Sprintf("category_id in %s", q))
	}
	var count int64
	tx := iDb.Count(&count)
	if tx.Error != nil {
		return nil, errors.New(custom_error.ProductDataIsNotExists)
	}
	r := iDb.Joins("Category").Joins("Brand").Scopes(internal.MyPaging(req.PageNo, req.PageSize)).Find(&productList)

	if r.RowsAffected < 1 {
		return nil, errors.New(custom_error.ProductDataIsNotExists)
	}
	for _, i := range productList {
		itemList = append(itemList, CovertProductModel2pb(i))
	}
	res.Total = int32(count)
	res.ProductItemRes = itemList

	return &res, nil
}

func (p ProductServer) BatchGetProduct(ctx context.Context, req *pb.BatchProductIdReq) (*pb.ProductsRes, error) {
	var res pb.ProductsRes
	var itemRes []*pb.ProductItemRes
	var proList []model.Product
	var count int64
	r := internal.DB.Where("id in ?", req.Ids).Count(&count).Find(&proList)
	if r.RowsAffected < 1 {
		return nil, errors.New(custom_error.ProductDataIsNotExists)
	}
	for _, i := range proList {
		itemRes = append(itemRes, CovertProductModel2pb(i))
	}
	res.Total = int32(count)
	res.ProductItemRes = itemRes
	return &res, nil
}

func (p ProductServer) GetProductDetail(ctx context.Context, req *pb.ProductItemReq) (*pb.ProductItemRes, error) {
	var res *pb.ProductItemRes
	var proMod model.Product
	r := internal.DB.First(&proMod, req.Id)
	if r.RowsAffected < 1 {
		return nil, errors.New(custom_error.ProductDataIsNotExists)
	}
	res = CovertProductModel2pb(proMod)
	return res, nil
}

func ConvertReq2Model(req *pb.CreateProductItem, category model.CateGory, brand model.Brand) model.Product {
	p := model.Product{
		CateGoryID: req.CategoryId,
		CateGory:   category,
		BrandID:    req.BrandId,
		Brand:      brand,
		Selling:    req.Selling,
		ShipFree:   req.ShipFree,
		IsPop:      req.IsPop,
		IsNew:      req.IsNew,
		Name:       req.Name,
		SN:         req.SN,
		FavNum:     req.FavNum,
		SoldNum:    req.SoldNum,
		Price:      req.Price,
		RealPrice:  req.RealPrice,
		ShortDesc:  req.ShortDesc,
		Image:      req.Images,
		DescImage:  req.DescImage,
		CoverImage: req.CoverImage,
	}
	return p
}

func CovertProductModel2pb(pro model.Product) *pb.ProductItemRes {
	p := &pb.ProductItemRes{
		Id:         pro.ID,
		CategoryId: pro.CateGoryID,
		BrandId:    pro.BrandID,
		Selling:    pro.Selling,
		ShipFree:   pro.ShipFree,
		IsPop:      pro.IsPop,
		IsNew:      pro.IsNew,
		Name:       pro.Name,
		SN:         pro.SN,
		FavNum:     pro.FavNum,
		SoldNum:    pro.SoldNum,
		Price:      pro.Price,
		RealPrice:  pro.RealPrice,
		ShortDesc:  pro.ShortDesc,
		CoverImage: pro.CoverImage,
		Images:     pro.Image,
		DescImage:  pro.DescImage,
		Category: &pb.CategoryShortItemRes{
			Id:   pro.CateGory.ID,
			Name: pro.CateGory.Name,
		},
		Brand: &pb.BrandItemRes{
			Id:   pro.Brand.ID,
			Name: pro.Brand.Name,
			Logo: pro.Brand.Logo,
		},
	}
	return p
}
